package com.hhd.form.service.impl;

import com.hhd.base.utils.CommonUtils;
import com.hhd.form.entity.*;
import com.hhd.form.service.*;
import com.hhd.form.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class DesignFormQueryServiceImpl implements IDesignFormQueryService {

    @Autowired
    IDesignFormDefinitionService formDefinitionService;

    @Autowired
    IDesignFormFieldDefinitionService formFieldDefinitionService;

    @Autowired
    IDesignFormActionDefinitionService formActionDefinitionService;

    @Autowired
    IDesignSubFormActionDefinitionService subFormActionDefinitionService;

    @Autowired
    IDesignFormFieldActionDefinitionService formFieldActionDefinitionService;

    @Autowired
    IDesignFormViewDefinitionService formViewDefinitionService;

    @Autowired
    IDesignFormMenuService formMenuService;

    @Autowired
    IDesignFormMenuShowFieldService formMenuShowFieldService;

    @Autowired
    IDesignFormMenuSearchFieldService formMenuSearchFieldService;

    @Autowired
    IDesignFormMenuSearchQueryService formMenuSearchQueryService;

    @Autowired
    IDesignFormMenuOrderFieldService formMenuOrderFieldService;

    @Override
    public FormDefinition queryById(String id) {
        FormDefinition formDefinition = queryFormDefinition(id);
        if (CommonUtils.isEmpty(formDefinition)) return null;
        loadFields(formDefinition);
        loadSubForms(formDefinition);
        loadActions(formDefinition);
        loadViews(formDefinition);
        loadMenus(formDefinition);
        return formDefinition;
    }

    private void loadMenus(FormDefinition formDefinition) {
        List<DesignFormMenu> list = formMenuService.lambdaQuery()
                .eq(DesignFormMenu::getFormId, formDefinition.getId())
                .orderByAsc(DesignFormMenu::getSort)
                .list();
        if (CommonUtils.isEmpty(list)) return;
        List<FormMenu> menus = CommonUtils.copyToList(list, FormMenu.class);
        for (FormMenu menu : menus) {
            loadShowFields(menu);
            loadSearchFields(menu);
            loadSearchQuerys(menu);
            loadOrderFields(menu);
        }
        formDefinition.setMenus(menus);
    }

    private void loadOrderFields(FormMenu menu) {
        List<DesignFormMenuOrderField> list = formMenuOrderFieldService.lambdaQuery()
                .eq(DesignFormMenuOrderField::getFormMenuId, menu.getId())
                .orderByAsc(DesignFormMenuOrderField::getSort)
                .list();
        List<OrderField> orderFields = CommonUtils.copyToList(list, OrderField.class);
        menu.setOrderFields(orderFields);
    }

    private void loadSearchQuerys(FormMenu menu) {
        List<DesignFormMenuSearchQuery> list = formMenuSearchQueryService.lambdaQuery()
                .eq(DesignFormMenuSearchQuery::getFormMenuId, menu.getId())
                .orderByAsc(DesignFormMenuSearchQuery::getSort)
                .list();
        List<SearchQuery> querys = CommonUtils.copyToList(list, SearchQuery.class);
        menu.setSearchQuerys(querys);
    }

    private void loadSearchFields(FormMenu menu) {
        List<DesignFormMenuSearchField> list = formMenuSearchFieldService.lambdaQuery()
                .eq(DesignFormMenuSearchField::getFormMenuId, menu.getId())
                .orderByAsc(DesignFormMenuSearchField::getSort)
                .list();
        if (CommonUtils.isEmpty(list)) return;
        List<SearchField> searchFields = CommonUtils.copyToList(list, SearchField.class);
        menu.setSearchFields(searchFields);
    }

    private void loadShowFields(FormMenu menu) {
        List<DesignFormMenuShowField> list = formMenuShowFieldService.lambdaQuery()
                .eq(DesignFormMenuShowField::getFormMenuId, menu.getId())
                .orderByAsc(DesignFormMenuShowField::getSort)
                .list();
        List<ShowField> showFields = CommonUtils.copyToList(list, ShowField.class);
        menu.setShowFields(showFields);
    }

    private void loadViews(FormDefinition formDefinition) {
        List<DesignFormViewDefinition> views = formViewDefinitionService.lambdaQuery()
                .eq(DesignFormViewDefinition::getFormId, formDefinition.getId())
                .orderByAsc(DesignFormViewDefinition::getSort)
                .list();
        formDefinition.setViews(views);
    }

    private void loadActions(FormDefinition formDefinition) {
        List<DesignFormActionDefinition> actions = formActionDefinitionService.lambdaQuery()
                .eq(DesignFormActionDefinition::getFormId, formDefinition.getId())
                .orderByAsc(DesignFormActionDefinition::getSort).list();
        if (CommonUtils.isEmpty(actions)) {
            actions = CommonUtils.newList();
        }
        List<FormAction> formActions = CommonUtils.copyToList(actions, FormAction.class);
        formDefinition.setActions(formActions);
        for (FormAction action : formActions) {
            loadSubFormActions(action);
            loadFieldActions(action);
        }
    }

    private void loadFieldActions(FormAction action) {
        action.setFieldActions(formFieldActionDefinitionService.lambdaQuery()
                .eq(DesignFormFieldActionDefinition::getActionId, action.getId())
                .orderByAsc(DesignFormFieldActionDefinition::getSort)
                .list());
    }

    private void loadSubFormActions(FormAction action) {
        action.setSubFormActions(subFormActionDefinitionService
                .lambdaQuery()
                .eq(DesignSubFormActionDefinition::getActionId, action.getId())
                .orderByAsc(DesignSubFormActionDefinition::getSort)
                .list());
    }

    private void loadSubForms(FormDefinition formDefinition) {
        List<DesignFormDefinition> subForms = formDefinitionService.lambdaQuery()
                .eq(DesignFormDefinition::getParentId, formDefinition.getId())
                .orderByAsc(DesignFormDefinition::getSort)
                .list();
        List<SubFormDefinition> formDefinitions = CommonUtils.copyToList(subForms, SubFormDefinition.class);
        for (SubFormDefinition definition : formDefinitions) {
            loadFields(definition);
        }
        formDefinition.setSubForms(formDefinitions);
    }

    private void loadFields(FormDefinition formDefinition) {
        List<DesignFormFieldDefinition> list = formFieldDefinitionService.lambdaQuery()
                .eq(DesignFormFieldDefinition::getFormId, formDefinition.getId())
                .orderByAsc(DesignFormFieldDefinition::getSort)
                .list();
        formDefinition.setFields(list);
    }

    private FormDefinition queryFormDefinition(String id) {
        DesignFormDefinition formDefinition = formDefinitionService.getById(id);
        if (CommonUtils.isEmpty(formDefinition)) return null;
        return CommonUtils.copyTo(formDefinition, FormDefinition.class);
    }
}
